package com.lmind.bean;

import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.util.Map;

public class BeanWalker {

	private ObjectWalker walker = new ObjectWalker();
	
	private Visitor internalVisitor = new Visitor();

	private List<String> includePackages;

	private IObjectVisitor visitor;

	public IObjectVisitor getVisitor() {
		return visitor;
	}

	public void setVisitor(IObjectVisitor visitor) {
		this.visitor = visitor;
	}

	public List<String> getIncludePackages() {
		return includePackages;
	}

	public void setIncludePackages(List<String> includePackages) {
		this.includePackages = includePackages;
	}

	public void walk(Object bean) throws IllegalAccessException,
			InvocationTargetException, NoSuchMethodException {
		walker.setVisitor(internalVisitor);
		walker.walk(bean);
	}

	private boolean shouldWalk(Object o) {
		
		if (o == null)
			return false;
		
		if (o instanceof List || o instanceof Map)
			return true;
		
		String className = o.getClass().getName();
		for (String pack : includePackages) {
			if (className.startsWith(pack)) {
				return true;
			}
		}
		return false;
	}

	class Visitor implements IObjectVisitor {

		@Override
		public void visitProperty(IWalkerContext context) {

			if (!shouldWalk(context.getValue())) {
				context.stop();
			}
			visitor.visitProperty(context);
		}

		@Override
		public void visitList(IWalkerContext context) {
			if (!shouldWalk(context.getValue())) {
				context.stop();
			}
			visitor.visitList(context);
		}

		@Override
		public void visitMap(IWalkerContext context) {
			if (!shouldWalk(context.getValue())) {
				context.stop();
			}
			visitor.visitMap(context);
		}

		@Override
		public void visitArray(IWalkerContext context) {
			if (!shouldWalk(context.getValue())) {
				context.stop();
			}
			visitArray(context);
		}

	}
}
